package com.github.gaojh.config;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author gaojh
 * @since 2020/3/23
 */
@Slf4j
public class Environment {

    private int port = 8080;

    private boolean enableWebsocket = false;

    private Props props;

    private static final Environment ME = new Environment();


    private Environment() {
        loadApplicationConfig();
        //再从系统配置项获取并覆盖
        initFromSystem();
        this.port = getInteger("server.port", 8080);
        this.enableWebsocket = getBoolean("flying.websocket.enable", false);
    }

    public static Environment me() {
        return ME;
    }

    private void loadApplicationConfig() {
        String application = System.getProperty("flying.application");
        if (StrUtil.isNotBlank(application)) {
            log.info("使用自定义配置文件：{}", application);
        } else {
            application = "application.properties";
        }

        props = new Props();
        if (FileUtil.exist(application)) {
            try {
                InputStream inputStream = FileUtil.getInputStream(application);
                props.load(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    private void initFromSystem() {
        Properties properties = System.getProperties();
        properties.stringPropertyNames().forEach(key -> props.setProperty(key, properties.getProperty(key)));

        if (log.isDebugEnabled()) {
            props.keySet().forEach(s -> log.debug("{} === {}", s, props.get(s)));
        }
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setEnableWebsocket(boolean enableWebsocket) {
        this.enableWebsocket = enableWebsocket;
    }

    public Integer getPort() {
        return this.port;
    }

    public boolean isEnableWebsocket() {
        return this.enableWebsocket;
    }

    public String getString(String key) {
        return props.getProperty(key);
    }

    public String getString(String key, String defaultValue) {
        return props.getProperty(key, defaultValue);
    }

    public Integer getInteger(String key) {
        String value = props.getProperty(key);
        if (value != null) {
            return Integer.parseInt(value);
        }
        return null;
    }

    public Integer getInteger(String key, Integer defaultValue) {
        String value = props.getProperty(key);
        if (value != null) {
            return Integer.parseInt(value);
        }
        return defaultValue;
    }

    public Long getLong(String key) {
        return props.getLong(key);
    }

    public Long getLong(String key, Long value) {
        return props.getLong(key, value);
    }

    public Double getDouble(String key) {
        return props.getDouble(key);
    }

    public Double getDouble(String key, Double value) {
        return props.getDouble(key, value);
    }

    public Boolean getBoolean(String key) {
        return props.getBool(key);
    }

    public Boolean getBoolean(String key, Boolean defaultValue) {
        return props.getBool(key, defaultValue);
    }

    public Object get(String key) {
        return props.get(key);
    }

    public Object get(String key, Object defaultValue) {
        return props.getOrDefault(key, defaultValue);
    }

    public void put(Object key, Object value) {
        props.put(key, value);
    }

    public boolean containsKey(String key) {
        return props.containsKey(key);
    }

    public Set<String> keys() {
        return props.keySet().stream().map(Object::toString).collect(Collectors.toSet());
    }
}
